package org.go.scheduler.database;

import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.ParseException;
import java.util.TimeZone;

import org.go.scheduler.database.util.StdJDBCConstants;
import org.go.trigger.CronScheduleBuilder;
import org.go.trigger.CronTrigger;
import org.go.trigger.Trigger;
import org.go.trigger.TriggerKey;
import org.go.util.Util;
import org.go.work.Work;

public class CronTriggerPersistenceDelegate implements TriggerPersistenceDelegate, StdJDBCConstants {

	protected String schedNameLiteral;
	protected String tablePrefix;

	@Override
	public boolean canHandleTriggerType(Trigger trigger) {
		return ((trigger instanceof CronTrigger) && !((CronTrigger) trigger).hasAdditionalProperties());
	}

	@Override
	public int deleteExtendedTriggerProperties(Connection conn, TriggerKey triggerKey) throws SQLException {

		PreparedStatement ps = null;

		try {
			ps = conn.prepareStatement(Util.rtp(DELETE_CRON_TRIGGER, tablePrefix, schedNameLiteral));
			ps.setString(1, triggerKey.getName());
			ps.setString(2, triggerKey.getGroup());

			return ps.executeUpdate();
		} finally {
			Util.closeStatement(ps);
		}
	}

	@Override
	public String getHandledTriggerTypeDiscriminator() {
		return TTYPE_CRON;
	}

	@Override
	public void initialize(String tablePrefix, String schedName) {
		this.tablePrefix = tablePrefix;
		this.schedNameLiteral = "'" + schedName + "'";
	}

	//@Override
	public int insertExtendedTriggerProperties(Connection conn, Trigger trigger, String state, Work jobDetail) throws SQLException, IOException {

		CronTrigger cronTrigger = (CronTrigger) trigger;

		PreparedStatement ps = null;

		try {
			ps = conn.prepareStatement(Util.rtp(INSERT_CRON_TRIGGER, tablePrefix, schedNameLiteral));
			ps.setString(1, trigger.getKey().getName());
			ps.setString(2, trigger.getKey().getGroup());
			ps.setString(3, cronTrigger.getCronExpression());
			ps.setString(4, cronTrigger.getTimeZone().getID());

			return ps.executeUpdate();
		} finally {
			Util.closeStatement(ps);
		}
	}

	@SuppressWarnings("null")
	@Override
	public TriggerPropertyBundle loadExtendedTriggerProperties(Connection conn, TriggerKey triggerKey) throws SQLException {

		PreparedStatement ps = null;
		ResultSet rs = null;

		try {
			ps = conn.prepareStatement(Util.rtp(SELECT_CRON_TRIGGER, tablePrefix, schedNameLiteral));
			ps.setString(1, triggerKey.getName());
			ps.setString(2, triggerKey.getGroup());
			rs = ps.executeQuery();

			if (rs.next()) {
				String cronExpr = rs.getString(COL_CRON_EXPRESSION);
				String timeZoneId = rs.getString(COL_TIME_ZONE_ID);

				CronScheduleBuilder cb = null;
				try {
					cb = CronScheduleBuilder.cronSchedule(cronExpr);
				} catch (ParseException neverHappens) {
					// Can't happen because the expression must have been valid in order to get persisted
				}

				if (timeZoneId != null)
					cb.inTimeZone(TimeZone.getTimeZone(timeZoneId));
				return null;
				//return new TriggerPropertyBundle(cb, null, null);
			}

			throw new IllegalStateException("No record found for selection of Trigger with key: '" + triggerKey + "' and statement: " + Util.rtp(SELECT_CRON_TRIGGER, tablePrefix, schedNameLiteral));
		} finally {
			Util.closeResultSet(rs);
			Util.closeStatement(ps);
		}
	}

	//@Override
	public int updateExtendedTriggerProperties(Connection conn, Trigger trigger, String state, Work jobDetail) throws SQLException, IOException {

		CronTrigger cronTrigger = (CronTrigger) trigger;

		PreparedStatement ps = null;

		try {
			ps = conn.prepareStatement(Util.rtp(UPDATE_CRON_TRIGGER, tablePrefix, schedNameLiteral));
			ps.setString(1, cronTrigger.getCronExpression());
			ps.setString(2, cronTrigger.getTimeZone().getID());
			ps.setString(3, trigger.getKey().getName());
			ps.setString(4, trigger.getKey().getGroup());

			return ps.executeUpdate();
		} finally {
			Util.closeStatement(ps);
		}
	}

}
